package com.cw.lang.common.mapper.provider.list;

import org.apache.ibatis.mapping.MappedStatement;

import com.cw.lang.common.exception.MybatisException;
import com.cw.lang.common.enums.EnumDialect;
import com.cw.lang.common.enums.EnumMybatisError;
import com.cw.lang.common.mapper.helper.SqlHelper;
import com.cw.lang.common.mapper.utils.DialectUtils;

import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;

/**
 * @author chenw
 * @version V2.1
 * @since 2.1.0 2019-03-20 14:15
 */
public class UpdateListProvider extends MapperTemplate {
    public UpdateListProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }

    /**
     * 批量更新，null值会被更新
     *
     * @param ms MappedStatement
     * @return sql语句
     */
    public String updateByPrimaryKeyList(MappedStatement ms) {
        return updateList(ms, false, false);
    }

    /**
     * 批量根据主键更新属性不为null的值
     *
     * @param ms MappedStatement
     * @return sql语句
     */
    public String updateByPrimaryKeySelectiveList(MappedStatement ms) {
        return updateList(ms, true, isNotEmpty());
    }

    /**
     * 批量更新
     *
     * @param ms MappedStatement
     * @param notNull 是否可为null
     * @param notEmpty 是否可为空
     * @return sql语句
     */
    private String updateList(MappedStatement ms, boolean notNull, boolean notEmpty) {
        // 获取数据库方言
        EnumDialect dialect = DialectUtils.getDialect(ms.getConfiguration()
            .getEnvironment()
            .getDataSource());
        // 暂时使用switch处理，会因为现在仅有2种方言，如果后续需要添加，则要考虑换成策略模式，参考 InsertListProviderWrapper#insertList
        switch (dialect) {
            case MYSQL:
                return mysqlUpdateList(ms, notNull, notEmpty);
            case ORACLE:
                return oracleUpdateList(ms, notNull, notEmpty);
            default:
                throw new MybatisException(EnumMybatisError.DIALECT_NOT_EXISTS.getCode(),
                    EnumMybatisError.DIALECT_NOT_EXISTS.getDescription());
        }
    }

    /**
     * oracle 批量更新
     *
     * @param ms MappedStatement
     * @param notNull 是否可为null
     * @param notEmpty 是否可为空
     * @return sql语句
     */
    private String oracleUpdateList(MappedStatement ms, boolean notNull, boolean notEmpty) {
        StringBuilder sql = new StringBuilder();
        Class<?> entityClass = getEntityClass(ms);
        String item = "record";
        // 针对oracle增加 begin end 符号
        sql.append("<foreach collection=\"list\" item=\"")
            .append(item)
            .append("\" open=\"begin\" close=\";end;\" separator=\";\" >");
        sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));
        sql.append(SqlHelper.updateSetColumnsForList(entityClass, item, notNull, notEmpty));
        sql.append(SqlHelper.wherePKColumnsWithPrefix(entityClass, item, true));
        sql.append("</foreach>");
        return sql.toString();
    }

    /**
     * oracle 批量更新
     *
     * @param ms MappedStatement
     * @param notNull 是否可为null
     * @param notEmpty 是否可为空
     * @return sql语句
     */
    private String mysqlUpdateList(MappedStatement ms, boolean notNull, boolean notEmpty) {
        StringBuilder sql = new StringBuilder();
        Class<?> entityClass = getEntityClass(ms);
        String item = "record";
        sql.append("<foreach collection=\"list\" item=\"")
            .append(item)
            .append("\" separator=\";\" >");
        sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));
        sql.append(SqlHelper.updateSetColumnsForList(entityClass, item, notNull, notEmpty));
        sql.append(SqlHelper.wherePKColumnsWithPrefix(entityClass, item, true));
        sql.append("</foreach>");
        return sql.toString();
    }
}
